﻿using System;
using System.Drawing;
using System.Runtime.InteropServices;

namespace DevelopTool.Common
{
    public class IconHelper
    {

        // 导入shell32.dll中的SHGetFileInfo函数，用于检索文件的信息
        [DllImport("shell32.dll", CharSet = CharSet.Auto)]
        private static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbFileInfo, uint uFlags);

        // 定义SHFILEINFO结构，用于接收SHGetFileInfo函数的信息
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
        private struct SHFILEINFO
        {
            public IntPtr hIcon; // 图标句柄
            public int iIcon; // 系统图标索引
            public uint dwAttributes; // 文件属性
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
            public string szDisplayName; // 显示名称
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
            public string szTypeName; // 类型名称
        };

        // 定义SHGetFileInfo函数的标志
        private const uint SHGFI_ICON = 0x000000100; // 获取图标
        private const uint SHGFI_LARGEICON = 0x000000000; // 获取大图标
        private const uint SHGFI_SMALLICON = 0x000000001; // 获取小图标
        private const uint SHGFI_USEFILEATTRIBUTES = 0x000000010; // 使用文件属性
        private const uint FILE_ATTRIBUTE_DIRECTORY = 0x00000010; // 文件夹属性

        /// <summary>
        /// 获取文件或文件夹的系统图标。
        /// </summary>
        /// <param name="filePath">文件或文件夹的路径。</param>
        /// <param name="smallIcon">是否获取小图标。</param>
        /// <returns>文件或文件夹的系统图标。</returns>
        public static Icon GetFileIcon(string filePath, bool smallIcon = true)
        {
            // 设置获取图标的标志
            uint flags = SHGFI_ICON | SHGFI_USEFILEATTRIBUTES;
            flags += smallIcon ? SHGFI_SMALLICON : SHGFI_LARGEICON;

            // 确定是否为文件夹
            uint attributes = (uint)(System.IO.Directory.Exists(filePath) ? FILE_ATTRIBUTE_DIRECTORY : 0);

            SHFILEINFO shinfo = new SHFILEINFO();
            // 调用SHGetFileInfo函数获取文件信息
            IntPtr hImg = SHGetFileInfo(filePath, attributes, ref shinfo, (uint)Marshal.SizeOf(shinfo), flags);

            // 如果获取图标失败，返回null
            if (shinfo.hIcon == IntPtr.Zero)
                return null;

            // 从图标句柄创建Icon对象并克隆以便于销毁句柄
            Icon icon = (Icon)Icon.FromHandle(shinfo.hIcon).Clone();
            // 销毁图标句柄，防止内存泄漏
            DestroyIcon(shinfo.hIcon);

            return icon;
        }

        // 导入user32.dll中的DestroyIcon函数，用于销毁图标句柄
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        private extern static bool DestroyIcon(IntPtr handle);

        /// <summary>
        /// 将图标缩放到指定的大小。
        /// </summary>
        /// <param name="icon">要缩放的图标。</param>
        /// <param name="size">目标大小。</param>
        /// <returns>缩放后的图标。</returns>
        public static Icon ResizeIcon(Icon icon, Size size)
        {
            Bitmap bitmap = new Bitmap(icon.ToBitmap(), size);
            return Icon.FromHandle(bitmap.GetHicon());
        }

        /// <summary>
        /// 获取图标的大小。
        /// </summary>
        /// <param name="icon">要获取大小的图标。</param>
        /// <returns>图标的大小。</returns>
        public static Size GetIconSize(Icon icon)
        {
            return icon.Size;
        }
    }
}
